package com.xukun.changgou.auth.filter;

import com.xukun.changgou.common.constants.CommonConstant;
import com.xukun.changgou.common.redis.RedisUtil;
import com.xukun.changgou.common.response.ResponseEnum;
import com.xukun.changgou.common.response.exception.BaseException;
import com.xukun.changgou.common.utils.HttpUtil;
import com.xukun.changgou.common.utils.JwtUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @Author xukun
 * @Date 2021-06-06 13:14
 * @Description 自定义token过滤器，用来处理调用该服务的内部接口inner未认证问题
 */
public class BaseTokenFilter extends BasicAuthenticationFilter {

    @Autowired
    private RedisUtil redisUtil;

    public BaseTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        //登录登录出直接放行
        String path = request.getServletPath();
        //访问内部接口，需要认证通过
        if (path.indexOf("/inner") != -1) {

            //获取token
            String token = request.getHeader(CommonConstant.TOKEN_HEADER);

            //校验token
            if (ObjectUtils.isEmpty(token)) {
                HttpUtil.doReturn(response, false, ResponseEnum.NOT_LOGIN);
                return;
            }

            //判断token是否在redis黑名单中
            if (redisUtil.hasKey(CommonConstant.REDIS_TOKEN_BLACK_LIST)) {
                Long len = redisUtil.lLen(CommonConstant.REDIS_TOKEN_BLACK_LIST);
                for (int i = 0; i < len; i++) {
                    if (token.equals(redisUtil.lIndex(CommonConstant.REDIS_TOKEN_BLACK_LIST, i).split("\\|")[0])) {
                        HttpUtil.doReturn(response, false, ResponseEnum.INVALID_TOKEN);
                        return;
                    }
                }
            }

            //获取token中的主体并判断有效性
            String username;
            try {
                String subject = JwtUtil.getSubject(token);
                username = subject.split("\\|")[1];
            } catch (BaseException e) {
                HttpUtil.doReturn(response, e);
                return;
            }
            // 通过token 获取账户信息，并且存入到将身份信息存放在安全系统的上下文
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        //放行
        chain.doFilter(request, response);
    }
}